import { AccessScopeContext, AccessDroitContext } from "qqlx-core";
import { isStringNotValid, toString } from "@lib/com.verify";
import { doBitsToDecimal, doDecimalToBits } from "@lib/com.binary";

/** 把权限范围的对象 scope 转换成合法的权限范围字符串
 * @refOwnerUUid32 翻译对象中，必须包含这个值
 * @path 翻译对象中，必须包含这个值
 */
export function getAccessScopeStr(context: AccessScopeContext) {
  const { refOwnerUUid32, path, resource0, resource1 } = context;
  if (isStringNotValid(refOwnerUUid32)) throw new Error(`无法写入管理人`);
  else if (isStringNotValid(path)) throw new Error(`无法写入资源范围`);

  const scope: string[] = [];
  for (const value of [refOwnerUUid32, path, resource0, resource1]) {
    const _value = toString(value);
    if (_value.length > 0) scope.push(_value);
    else break;
  }

  return scope.join("@");
}

/** 把权限范围 scope 翻译成对象
 * @refOwnerUUid32 必须存在
 * @path 必须存在
 */
export function getAccessScopeContext(scopeStr: string): AccessScopeContext {
  const str = toString(scopeStr).split("@");
  const transfer: AccessScopeContext = {
    refOwnerUUid32: str[0] || "",
    path: str[1] || "",
    resource0: str[2] || "",
    resource1: str[3] || "",
  };

  if (isStringNotValid(transfer.refOwnerUUid32)) throw new Error(`无法读取管理人`);
  else if (isStringNotValid(transfer.path)) throw new Error(`无法读取资源范围`);
  return transfer;
}

/** 根据权限数字，返回权限对象 */
export function getAccessDroitContext(droit: number): AccessDroitContext {
  const { bits } = doDecimalToBits(droit, 5);
  return {
    query: bits[4] === "1",
    create: bits[3] === "1",
    update: bits[2] === "1",
    delete: bits[1] === "1",
    download: bits[0] === "1",
  };
}

/** 根据权限数字，返回权限对象 */
export function getAccessDroitValue(context: Partial<AccessDroitContext>): number {
  const list = [
    //
    context.download ? "1" : "0",
    context.delete ? "1" : "0",
    context.update ? "1" : "0",
    context.create ? "1" : "0",
    context.query ? "1" : "0",
  ];
  return doBitsToDecimal(list.join("")).decimal;
}

/** 默认全是 false */
export function getAccessDataDefault(value?: boolean): AccessDroitContext {
  return {
    query: !!value,
    create: !!value,
    update: !!value,
    delete: !!value,
    download: !!value,
  };
}
